Linker Script

Source code -> compiler -> Assembler -> Object code -> Linker -> Executable file -> Loader

链接器是将多个obj模块链接成为一个obj文件的程序,说白了就是一个缝合器,将程序进行缝合,本文将对基本的linker script进行介绍。

基本概念

链接器

将一个或多个输入文件链接成为一个输出文件(不一定是可执行文件,也有可能是缝合成一个更大的库)

图片名称

文件

  • 输入文件:待链接的目标文件或链接脚本文件,输入文件内的section为输入section

  • 输出文件:目标文件或可执行文件(目标文件在linux下一般为ELF格式),输出文件内的section为输出section

section

section类型

对程序划分的段,输入文件内的section叫输入section,输出文件为输出section,一个section至少包含名字和大小,大部分还包含与其关联的一块数据,成为section content。一个section可被标记为可加载的(loadable)可分配的(allocatable),如果一个section不可加载或分配,那么一般包含调试信息(可使用objdump查看)。

  • loadable section:输出文件运行时,对应的内容被加载到进程地址空间
  • allocatable section:内容为空的section可被标记为可分配的,在输出文件运行时,会预先分配section指定大小的内存(某些情况下该内存强制为0)

section地址

每个可加载或分配的section一般包含两个地址:VMA和LMA,一般情况下两者相同

  • VMA:虚拟内存地址或程序地址空间地址(运行地址)
  • LMA:加载内存地址或进程地址空间地址(加载地址)

Linux下链接器使用

一个script范例及讲解

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* Simple linker script for the JOS kernel.
See the GNU ld 'info' manual ("info ld") to learn the syntax. */

OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)

SECTIONS // 使用SECTION关键字表示开始设置SECTION
{
/* Link the kernel at this address: "." means the current address */
. = 0xF0100000; // 设置location counter

/* AT(...) gives the load address of this section, which tells
the boot loader where to load the kernel in physical memory */
.text : AT(0x100000) { // 定义一个.text section,位置在(0x100000),
// 所有的*(.text)都会被归入其中,*代表通配符
*(.text .stub .text.* .gnu.linkonce.t.*)
}

PROVIDE(etext = .); /* Define the 'etext' symbol to this value */

.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
}

/* Include debugging information in kernel memory */
.stab : {
PROVIDE(__STAB_BEGIN__ = .);
*(.stab);
PROVIDE(__STAB_END__ = .);
BYTE(0) /* Force the linker to allocate space
for this section */
}

.stabstr : {
PROVIDE(__STABSTR_BEGIN__ = .); // 令__STABSTR_BEGIN__为counter所在的地址
*(.stabstr);
PROVIDE(__STABSTR_END__ = .);
BYTE(0) /* Force the linker to allocate space
for this section */
}

/* Adjust the address for the data segment to the next page */
. = ALIGN(0x1000);

/* The data segment */
.data : {
*(.data)
}

.bss : {
PROVIDE(edata = .);
*(.bss)
PROVIDE(end = .);
BYTE(0)
}


/DISCARD/ : {
*(.eh_frame .note.GNU-stack)
}
}

名词解释

Location counter .

.是链接器中的location counter,表示目前所在的location,SECTIONS开始时默认为0,可以人为调整其位置。同时,location counter会随着输出section的增加自动增加。

参考文献

0%